# -*- python -*-
# ex: set syntax=python:

# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# This is the buildmaster config file for the 'nacl' bot. It must
# be installed as 'master.cfg' in your buildmaster's base directory
# (although the filename can be changed with the --basedir option to
# 'mktap buildbot master').

# It has one job: define a dictionary named BuildmasterConfig. This
# dictionary has a variety of keys to control different aspects of the
# buildmaster. They are documented in docs/config.xhtml .

import posixpath

from buildbot.scheduler import Scheduler

from common import chromium_utils

from master import build_utils
from master import svn_poller_with_comparator
from master import gitiles_poller
from master import master_utils
from master import slaves_list
from master.factory import chromium_factory
from master.factory import gclient_factory

import config
import master_site_config

ActiveMaster = master_site_config.NativeClientSDK

# This is the dictionary that the buildmaster pays attention to. We also use
# a shorter alias to save typing.
c = BuildmasterConfig = {}

config.DatabaseSetup(c, require_dbconfig=ActiveMaster.is_production_host)

####### CHANGESOURCES

def ChromiumNativeClientChangeFilter(commit_json, branch):
  if 'tree_diff' not in commit_json:
    return False
  for diff_entry in commit_json['tree_diff']:
    path = diff_entry['new_path']
    if (path == 'DEPS' or
        path.startswith('native_client_sdk/') or
        path.startswith('ppapi/')):
      return True
  return False


def NativeClientSDKReleaseTreeFileSplitter(path):
  """Filter chromium commits to those relevant to the sdk release.

  Arguments:
    path: a path which svn reports has changed.
  Returns:
    A tuple containing (branchname, subpath).
  """
  return ('multirel', path)


multi_poller = gitiles_poller.GitilesPoller(
    repo_url=config.Master.git_server_url + '/chromium/src',
    svn_branch='multi',
    change_filter=ChromiumNativeClientChangeFilter)

multirel_poller = svn_poller_with_comparator.SvnPollerWithComparator(
    multi_poller.comparator,
    svnurl=('%s/tools/buildspec/build/chrome-official' %
        config.Master.trunk_internal_url),
    svnbin=chromium_utils.SVN_BIN,
    split_file=NativeClientSDKReleaseTreeFileSplitter,
    revlinktmpl=(
        'http://chromesshgw.corp.google.com/viewvc/chrome-internal?view=rev&revision=%s'),
    pollinterval=10)

c['change_source'] = [
    multi_poller,
    multirel_poller,
]


####### BUILDERS

# buildbot/process/factory.py provides several BuildFactory classes you can
# start with, which implement build processes for common targets (GNU
# autoconf projects, CPAN perl modules, etc). The factory.BuildFactory is the
# base class, and is configured with a series of BuildSteps. When the build
# is run, the appropriate buildslave is told to execute each Step in turn.

# the first BuildStep is typically responsible for obtaining a copy of the
# sources. There are source-obtaining Steps in buildbot/process/step.py for
# CVS, SVN, and others.


# The identifier of the factory is the build configuration. If two factories
# are using the same build configuration, they should have the same identifier.

# BuilderTesters using a custom build configuration.
all_factories = []
schedulers = []

branches = ['multi', 'multirel']
for branch in branches:
  factories = []

  if branch == 'multi':
    branch_ext = '-multi'
    official = False
    solution = None
  elif branch == 'multirel':
    branch_ext = '-multirel'
    official = True
    solution = gclient_factory.GClientSolution(
        '%s/tools/buildspec/build/chrome-official' %
            config.Master.trunk_internal_url,
        custom_vars_list=[
            ('svn_url', config.Master.server_url),
            ('googlecode_url', config.Master.googlecode_url),
            ('sourceforge_url', config.Master.sourceforge_url),
            ('webkit_trunk', config.Master.webkit_trunk_url),
        ],
        custom_deps_list=[
            ('src/pdf', None),
            ('src-pdf', None),
        ],
        needed_components={},
        name='chrome-official')
  else:
    assert False

  m_win = chromium_factory.ChromiumFactory(
      build_dir='src/build', target_platform='win32')
  m_linux = chromium_factory.ChromiumFactory(
      build_dir='src/out', target_platform='linux2')
  m_mac = chromium_factory.ChromiumFactory(
      build_dir='src/out', target_platform='darwin')
  if solution:
    for m in [m_win, m_linux, m_mac]:
      while m._solutions:
        m._solutions.pop()
      m._solutions.append(solution)
  # Some shortcut to simplify the code below.
  F_WIN = m_win.ChromiumFactory
  F_LINUX = m_linux.ChromiumFactory
  F_MAC = m_mac.ChromiumFactory

  # SDKs
  # Label each factory with a catergory code like:
  # '1trunk' indicating: category 1, branch trunk.
  code = str(branches.index(branch) + 1) + branch

  factory_properties_linux = {
    'annotated_script': 'nacl_sdk_buildbot_run.py',
    'no_gclient_branch': True,
    'nuke_and_pave': official,
    'gclient_env': {
        'GYP_DEFINES': 'fastbuild=1',
    },
  }
  factory_properties_win = {
    'annotated_script': 'nacl_sdk_buildbot_run.py',
    'no_gclient_branch': True,
    'nuke_and_pave': official,
    'gclient_env': {
        'GYP_DEFINES': 'fastbuild=1',
    },
  }
  factory_properties_mac = {
    'annotated_script': 'nacl_sdk_buildbot_run.py',
    'no_gclient_branch': True,
    'nuke_and_pave': official,
    'gclient_env': {
        'GYP_DEFINES': 'fastbuild=1',
        'GYP_GENERATORS': 'ninja',
    },
  }

  tests = ['annotated_steps']

  if branch == 'multirel':
    # TODO(binji) As of March 14, 2014, the chromium_builder_nacl_sdk target
    # doesn't exist on all Chrome release branches. When it does, use it.
    builder_target = 'chromium_builder_tests'
  else:
    builder_target = 'chromium_builder_nacl_sdk'

  factories.append(['windows-sdk' + branch_ext, code,
                    F_WIN(clobber=True, target='Release', tests=tests,
                          slave_type='Builder',
                          project='all.sln;' + builder_target,
                          options=['--compiler=goma'],
                          factory_properties=factory_properties_win)])
  factories.append(['mac-sdk' + branch_ext, code,
                    F_MAC(clobber=True, target='Release', tests=tests,
                          slave_type='Builder',
                          options=['--build-tool=ninja',
                                   '--compiler=goma-clang',
                                   '--', builder_target],
                          factory_properties=factory_properties_mac)])
  factories.append(['linux-sdk' + branch_ext, code,
                    F_LINUX(clobber=True, target='Release', tests=tests,
                            slave_type='Builder',
                            options=['--compiler=goma', builder_target],
                            factory_properties=factory_properties_linux)])
  if branch == 'multi':
    factories.append(['linux-sdk-bionic' + branch_ext, code,
                      F_LINUX(clobber=True, target='Release', tests=tests,
                              slave_type='Builder',
                              options=['--compiler=goma', builder_target],
                              factory_properties=factory_properties_linux)])
    factories.append(['linux-sdk-asan' + branch_ext, code,
                      F_LINUX(clobber=True, target='Release', tests=tests,
                              slave_type='Builder',
                              options=['--compiler=goma', builder_target],
                              factory_properties=factory_properties_linux)])
  s_nacl = Scheduler(
      name='nacl-' + branch,
      branch=branch,
      treeStableTimer=0,
      builderNames=[f[0] for f in factories],
  )

  schedulers.append(s_nacl)
  all_factories += factories

c['schedulers'] = schedulers

def mergeRequests(req1, req2):
  if (req1.buildername.endswith('-multirel') or
      req2.buildername.endswith('-multirel')):
    return False
  return req1.source.canBeMergedWith(req2.source)

c['mergeRequests'] = mergeRequests

# Convert factories to a list of (factory_name, factory_object) pairs.
factories_bare = [(f[0], f[2]) for f in factories]
# Create mapping of builder name to list of steps.
builder_steps = build_utils.ExtractFactoriesSteps(factories_bare)
all_steps = build_utils.AllFactoriesSteps(factories_bare)





# ----------------------------------------------------------------------------
# BUILDER DEFINITIONS

# The 'builders' list defines the Builders. Each one is configured with a
# dictionary, using the following keys:
#  name (required): the name used to describe this bilder
#  slavename (required): which slave to use, must appear in c['slaves']
#  builddir (required): which subdirectory to run the builder in
#  factory (required): a BuildFactory to define how the build is run
#  periodicBuildTime (optional): if set, force a build every N seconds
#  category (optional): it is not used in the normal 'buildbot' meaning. It is
#                       used by gatekeeper to determine which steps it should
#                       look for to close the tree.
#

c['builders'] = []
slaves = slaves_list.SlavesList('slaves.cfg', 'NativeClientSDK')
for f in all_factories:
  if 'multirel' in f[0]:
    sbuild = 'sdk-rel'
  else:
    sbuild = 'sdk'
  c['builders'].append({
      'name': f[0],
      'slavenames': slaves.GetSlavesName(builder=f[0]),
      'builddir': f[0],
      'slavebuilddir': sbuild,
      'factory': f[2],
      'category': '%s|full' % f[1],
      # Don't enable auto_reboot for people testing locally.
      'auto_reboot': ActiveMaster.is_production_host,
  })


####### BUILDSLAVES

# The 'slaves' list defines the set of allowable buildslaves. List all the
# slaves registered to a builder. Remove dupes.
c['slaves'] = master_utils.AutoSetupSlaves(c['builders'],
                                           config.Master.GetBotPassword())

# Make sure everything works together.
master_utils.VerifySetup(c, slaves)


####### STATUS TARGETS

# Buildbot master url:
# Must come before AutoSetupMaster().
c['buildbotURL'] = ActiveMaster.buildbot_url

# Adds common status and tools to this master.
master_utils.AutoSetupMaster(c, ActiveMaster,
                             order_console_by_time=True,
                             tagComparator=multi_poller.comparator,
                             public_html='../master.chromium/public_html',
                             templates=['./templates',
                                        '../master.client.nacl/templates'])
